package com.bnzjy.srb.core.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.bnzjy.common.exception.Assert;
import com.bnzjy.common.result.ResponseEnum;
import com.bnzjy.srb.base.pojo.dto.SmsDto;
import com.bnzjy.srb.core.enums.TransTypeEnum;
import com.bnzjy.srb.core.hfb.FormHelper;
import com.bnzjy.srb.core.hfb.HfbConst;
import com.bnzjy.srb.core.hfb.RequestHelper;
import com.bnzjy.srb.core.mapper.UserInfoMapper;
import com.bnzjy.srb.core.pojo.bo.TransFlowBO;
import com.bnzjy.srb.core.pojo.entity.UserAccount;
import com.bnzjy.srb.core.mapper.UserAccountMapper;
import com.bnzjy.srb.core.pojo.entity.UserInfo;
import com.bnzjy.srb.core.service.TransFlowService;
import com.bnzjy.srb.core.service.UserAccountService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bnzjy.srb.core.service.UserBindService;
import com.bnzjy.srb.core.service.UserInfoService;
import com.bnzjy.srb.core.util.LendNoUtils;
import com.bnzjy.srb.rabbitutil.constant.MQConst;
import com.bnzjy.srb.rabbitutil.service.MQService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;

/**
 * <p>
 * 用户账户 服务实现类
 * </p>
 *
 * @author Helen
 * @since 2021-12-13
 */
@Service
@Slf4j
public class UserAccountServiceImpl extends ServiceImpl<UserAccountMapper, UserAccount> implements UserAccountService {
    
    @Resource
    UserInfoMapper userInfoMapper;
    
    @Resource
    TransFlowService transFlowService;
    
    @Resource
    UserBindService userBindService;
    
    @Resource
    UserAccountService userAccountService;
    
    @Resource
    UserInfoService userInfoService;

    @Resource
    MQService mqService;
    
    /**
     * 会员充值
     * @param chargeAmt
     * @param userId
     * @return
     */
    @Override
    public String commitCharge(BigDecimal chargeAmt, Long userId) {
        
        UserInfo userInfo = userInfoMapper.selectById(userId);
        // 绑定账户协议号
        String bindCode = userInfo.getBindCode();
        
        // 判断账户绑定状态
        Assert.notEmpty(bindCode, ResponseEnum.USER_NO_AMOUNT_ERROR);
    
        HashMap<String, Object> paramHashMap = new HashMap<>();
        paramHashMap.put("agentId", HfbConst.AGENT_ID);
        paramHashMap.put("agentBillNo", LendNoUtils.getNo());
        paramHashMap.put("bindCode", bindCode);
        paramHashMap.put("chargeAmt", chargeAmt);
        paramHashMap.put("feeAmt", new BigDecimal("0"));
        paramHashMap.put("notifyUrl", HfbConst.RECHARGE_NOTIFY_URL);//检查常量是否正确
        paramHashMap.put("returnUrl", HfbConst.RECHARGE_RETURN_URL);
        paramHashMap.put("timestamp", RequestHelper.getTimestamp());
        String sign = RequestHelper.getSign(paramHashMap);
        paramHashMap.put("sign", sign);
    
        //构建充值自动提交表单
        String formStr = FormHelper.buildForm(HfbConst.RECHARGE_URL, paramHashMap);
        return formStr;
    }
    
    /**
     * 充值回调接口
     * @param paramMap
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String notify(Map<String, Object> paramMap) {
        
        log.info("充值成功：" + JSONObject.toJSONString(paramMap));
        
        // 判断交易流水是否存在
        String agentBillNo = (String) paramMap.get("agentBillNo");      // 商户充值订单号
        boolean isSave = transFlowService.isSaveTransFlow(agentBillNo);
        if (isSave) {
            log.warn("幂等性返回");
            return agentBillNo;
        }
    
        String bindCode = (String)paramMap.get("bindCode");         //充值人绑定协议号
        String chargeAmt = (String)paramMap.get("chargeAmt");       //充值金额
        
        // 优化
        baseMapper.updateAccount(bindCode, new BigDecimal(chargeAmt), new BigDecimal(0));
    
        //增加交易流水
        //TODO
//        String agentBillNo = (String) paramMap.get("agentBillNo");      // 商户充值订单号
        TransFlowBO transFlowBO = new TransFlowBO(agentBillNo, bindCode, new BigDecimal(chargeAmt), TransTypeEnum.RECHARGE, "充值");
        transFlowService.saveTransFlow(transFlowBO);
        
        // 发消息
        // TODO 2 用rabbit-mq 发消息
        log.info("发消息");
        String mobile = userInfoService.getMobileByBindCode(bindCode);
        SmsDto smsDTO = new SmsDto();
        smsDTO.setMobile(mobile);
        smsDTO.setMessage("充值成功");
        mqService.sendMessage(MQConst.EXCHANGE_TOPIC_SMS, MQConst.ROUTING_SMS_ITEM, smsDTO);

        return "success";
    }
    
    /**
     * 账户余额信息接口
     * @param userId
     * @return
     */
    @Override
    public BigDecimal getAccount(Long userId) {
        // 根据userId查找用户账户
        //  创建一个新的
        QueryWrapper<UserAccount> userAccountQueryWrapper = new QueryWrapper<>();
        // 用户id，指定用户的id
        userAccountQueryWrapper.eq("user_id", userId);
        // 根据id 查询唯一的用户账户
        UserAccount userAccount = baseMapper.selectOne(userAccountQueryWrapper);
        // 定义用户的帐户
        BigDecimal amount = userAccount.getAmount();
        
        return amount;
    }
    
    /**
     * 用户进行提现操作
     * @param fetchAmt
     * @param userId
     * @return
     */
    @Override
    public String commitWithdraw(BigDecimal fetchAmt, Long userId) {
        // 账户可用余额充足：当前用户的余额 >= 当前用户的提现金额
        BigDecimal amount = userAccountService.getAccount(userId);//获取当前用户的账户余额
        Assert.isTrue(amount.doubleValue() >= fetchAmt.doubleValue(),
            ResponseEnum.NOT_SUFFICIENT_FUNDS_ERROR);
       
        String bindCode = userBindService.getBindCodeByUserId(userId);
      
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("agentId", HfbConst.AGENT_ID);
        paramMap.put("agentBillNo", LendNoUtils.getWithdrawNo());
        paramMap.put("bindCode", bindCode);
        paramMap.put("fetchAmt", fetchAmt);
        paramMap.put("feeAmt", new BigDecimal(0));
        paramMap.put("notifyUrl", HfbConst.WITHDRAW_NOTIFY_URL);
        paramMap.put("returnUrl", HfbConst.WITHDRAW_RETURN_URL);
        paramMap.put("timestamp", RequestHelper.getTimestamp());
        
        String sign = RequestHelper.getSign(paramMap);
        paramMap.put("sign", sign);
       
        //构建自动提交表单
        String formStr = FormHelper.buildForm(HfbConst.WITHDRAW_URL, paramMap);
        return formStr;
    }
    
    /**
     * 回调接口实现
     * @param paramMap
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void notifyWithdraw(Map<String, Object> paramMap) {
    
        log.info("提现成功");
        String agentBillNo = (String)paramMap.get("agentBillNo");
        boolean result = transFlowService.isSaveTransFlow(agentBillNo);
        if(result){
            log.warn("幂等性返回");
            return;
        }
       
        String bindCode = (String)paramMap.get("bindCode");
        String fetchAmt = (String)paramMap.get("fetchAmt");
       
        //根据用户账户修改账户金额
        baseMapper.updateAccount(bindCode, new BigDecimal("-" + fetchAmt), new BigDecimal(0));
       
        //增加交易流水
        TransFlowBO transFlowBO = new TransFlowBO(
            agentBillNo,
            bindCode,
        new BigDecimal(fetchAmt),
        
        TransTypeEnum.WITHDRAW, "提现");
        
        transFlowService.saveTransFlow(transFlowBO);
    }
}
